/**
 * @file hiddenType.h
 * @brief Definisce una struttura che permetta di astrarre i dati
 * dal contesto in cui vengono utilizzati.
 *
 * Nel file vengono definite le strutture e le funzioni per gestirle.
 *
 * @date Mar 16, 2012
 * @author Francesco Corvino
 */

#ifndef HIDDENTYPE_H_
#define HIDDENTYPE_H_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/**
 * @brief Permette di utilizzare un tipo di dato nascosto e che quindi può variare in base alle necessità.
 *
 * Meccanismo: l'utilizzatore definisce una variabile di questo tipo e assegna un valore al campo hiddentype
 * rappresentate il vero contenuto, cioè quindi i dati necessari per poter interpretare una variabile.
 * Insieme ai dati definisce anche l'interpreter cioè un metodo per poter dare un significato al valore della
 * variabile.
 * Il valore potrebbe cambiare in base al contesto applicativo perciò il metodo interpreter prende due argomenti
 * il primo che è generalmente l'hiddentype stesso e il secondo che rappresenta il contesto.
 *
 * @see getHiddenTypeToString esempio di interpreter generalmente utilizzato per ottere le informazioni sui comandi.
 */
typedef struct hiddenType {
	/**
	 * @brief nell'attributo hiddentype si può assegnare un puntatore a qualsiasi forma di dato.
	 */
	 void * hiddentype;

	 /**
	  * @brief dimensione dell'oggetto puntato in hiddentype.
	  */
	 size_t size;

	 /**
	  * @brief Puntatore alla funzione che si deve occupare della deallocazione della memoria
	  * occupata da data.
	  *
	  * @param data verrà passato il puntatore data quando viene invocato il destroy dell'oggeto HiddenType
	  */
	 void (*destroy)(void*data);

	 /**
	 * @brief interpretfnc permette di ottenere un valore valido in base al contesto.
	 *
	 * @param data di solito è la stessa hiddentype
	 * @param context il contesto nel quale bisogna interpretare la variabile
	 */
	 void * (*interpretfnc)(void* data,void* context);

} HiddenType;

/////////////////////////////////////////////////////////////////////////////////////////
////// Proprietà dell'oggetto ///////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////

/**
 * @brief Inizializza un oggetto HiddenType.
 *
 * @param ht puntatore all'oggetto da inizializzare
 * @param data dati da nascondere
 * @param size dimensione dei dati
 */
void HiddenType_init(HiddenType*ht,void * data, size_t size);

/**
 * Dealloca la memoria allocata da un oggetto HiddenType.
 * @param ht
 */
void HiddenType_destroy(HiddenType *ht);

/**
 * @brief Cambia i dati della struttura nascosta.
 * @param ht puntatore a hiddentype da modificare
 * @param data puntatore ai valori da sostituire
 * @param size grandezza occupata dai valori da sostituire
 * @return valore della struttura precedente.
 */
void* HiddenType_change(HiddenType*ht,void *data, size_t size);

/////////////////////////////////////////////////////////////////////////////////////////
////// Funzioni ausiliarie /////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////

void * HiddenType_executeInterpreter(HiddenType* ht, void * context);

char* getHiddenTypeToString(void * value, void * context);

#endif /* HIDDENTYPE_H_ */
